package com.kyrie.lib_sys.utils.learn.TimeDemo;

import com.kyrie.lib_sys.application.timeApplys.pojo.entity.TimeRecord;
import com.kyrie.lib_sys.application.timeApplys.pojo.entity.ValidationResult;

import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;

/**
 * 工单时间统一校验工具类 (新版 功能完善版 )
 */
public class TimeValidator {

    /**
     * 校验前端传入的时间记录列表（支持单个或多个时间点、支持重叠检查）
     */
    public static ValidationResult validateRecords(
            List<TimeRecord> inputRecords,
            List<TimeRecord> existingRecords) {

        ValidationResult result = new ValidationResult();

        // 所有需要检查的记录（不论是一个点还是多个点）
        List<TimeRangeWrapper> rangeWrappers = new ArrayList<>();

        for (int i = 0; i < inputRecords.size(); i++) {
            TimeRecord record = inputRecords.get(i);
            String label = "记录" + (i + 1);

            // 1. 校验时间顺序
            List<TimePoint> points = getValidTimePoints(record);
            for (int j = 0; j < points.size() - 1; j++) {
                TimePoint current = points.get(j);
                TimePoint next = points.get(j + 1);
                if (!next.time.isAfter(current.time)) {
                    result.addError(String.format("%s字段 [%s(%s)] 应早于 [%s(%s)]",
                            label, current.fieldName, current.time,
                            next.fieldName, next.time));
                }
            }

            // 2. 收集可以作为区间比较的 prepareTime ~ completeTime
            if (record.getPrepareTime() != null && record.getCompleteTime() != null) {
                rangeWrappers.add(new TimeRangeWrapper(record.getPrepareTime(), record.getCompleteTime(), label));
            }
        }

        // 3. 校验 inputRecords 内部是否重叠
        for (int i = 0; i < rangeWrappers.size(); i++) {
            for (int j = i + 1; j < rangeWrappers.size(); j++) {
                TimeRangeWrapper r1 = rangeWrappers.get(i);
                TimeRangeWrapper r2 = rangeWrappers.get(j);
                if (isOverlap(r1, r2)) {
                    result.addError(String.format("%s[%s ~ %s] 与 %s[%s ~ %s] 时间重叠",
                            r1.label, r1.start, r1.end,
                            r2.label, r2.start, r2.end));
                }
            }
        }

        // 4. 与已有记录比较是否重叠
        if (existingRecords != null && !existingRecords.isEmpty()) {
            for (int i = 0; i < rangeWrappers.size(); i++) {
                TimeRangeWrapper newRange = rangeWrappers.get(i);
                for (int j = 0; j < existingRecords.size(); j++) {
                    TimeRecord existing = existingRecords.get(j);
                    if (existing.getPrepareTime() != null && existing.getCompleteTime() != null) {
                        TimeRangeWrapper existRange = new TimeRangeWrapper(
                                existing.getPrepareTime(), existing.getCompleteTime(), "已有记录" + (j + 1));
                        if (isOverlap(newRange, existRange)) {
                            result.addError(String.format("%s[%s ~ %s] 与 %s[%s ~ %s] 时间重叠",
                                    newRange.label, newRange.start, newRange.end,
                                    existRange.label, existRange.start, existRange.end));
                        }
                    }
                }
            }
        }

        return result;
    }

    // 获取非空时间点（按业务顺序）
    private static List<TimePoint> getValidTimePoints(TimeRecord record) {
        List<TimePoint> points = new ArrayList<>();
        addIfNotNull(points, "prepareTime", record.getPrepareTime());
        addIfNotNull(points, "travelTime", record.getTravelTime());
        addIfNotNull(points, "startTime", record.getStartTime());
        addIfNotNull(points, "completeTime", record.getCompleteTime());
        return points;
    }

    private static void addIfNotNull(List<TimePoint> list, String fieldName, LocalDateTime time) {
        if (time != null) {
            list.add(new TimePoint(fieldName, time));
        }
    }

    private static boolean isOverlap(TimeRangeWrapper r1, TimeRangeWrapper r2) {
        return r1.start.isBefore(r2.end) && r2.start.isBefore(r1.end);
    }

    // 内部结构类
    private static class TimePoint {
        String fieldName;
        LocalDateTime time;

        TimePoint(String fieldName, LocalDateTime time) {
            this.fieldName = fieldName;
            this.time = time;
        }
    }

    private static class TimeRangeWrapper {
        LocalDateTime start;
        LocalDateTime end;
        String label;

        TimeRangeWrapper(LocalDateTime start, LocalDateTime end, String label) {
            this.start = start;
            this.end = end;
            this.label = label;
        }
    }
}
